import type { ProcessBlock, BlockProcessor, PreBlock, PreCode, Row } from '../types';

const FENCE = '```';

const isBlockBegin = (row: Row) => row.value.startsWith(FENCE);

/**
 * ```
 *              <```> | <else>
 *         +-----------------------+
 *        /                         \
 *       V           <```>           \
 *    INIT(0) -------------------> CODE(1)
 *     ^   |         resule.push(code)  |
 *     |   |                        ^   |
 *     |   | <else>                 |   | <row>
 *     |   V                        |   V
 *  result.push(block)       result.last.rows.push(block)
 * ```
 */
const processBlock: ProcessBlock = (pbs) => {
  const result: PreBlock[] = [];
  let state = 0;
  for (const block of pbs) {
    const { type } = block;
    switch (state) {
      case 0: {
        if (type === 'row') {
          if (isBlockBegin(block)) {
            state = 1;
            result.push({ type: 'code', rows: [] });
          } else {
            result.push(block);
          }
        } else {
          result.push(block);
        }
        break;
      }
      case 1: {
        if (type === 'row') {
          if (isBlockBegin(block)) {
            state = 0;
          } else {
            (result[result.length - 1] as PreCode).rows.push(block);
          }
        } else {
          result.push(block);
          state = 0;
        }
        break;
      }
    }
  }
  return result;
};

const fencedCodeProcessor: BlockProcessor = {
  isBlockBegin,
  process: processBlock,
};

export default {
  processor: fencedCodeProcessor,
};
